/*
 * Copyright (C) 2009 M. Hautle.
 * 
 * This file is part of TrackedBean.
 * 
 * TrackedBean is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * TrackedBean is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with TrackedBean. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.simpleel.util;

import static ch.simpleel.utils.BeanTestUtil.*;
import static junit.framework.Assert.*;
import java.util.*;
import org.junit.*;
import ch.simpleel.data.*;

/**
 * Test for the utility package.
 * 
 * @author M. Hautle
 */
public class GeneralUtils {
    /**
     * Test for {@link MiscUtils#copyValues(Object, Object)}.
     * 
     * @throws Exception
     */
    @Test
    public void testFlatCopy() throws Exception {
        // simple
        final ABean src = DataFactory.createSimple();
        final ABean dst = new ABean();
        MiscUtils.copyValues(src, dst);
        checkBeans("Flat copy was not successfull", src, dst);
        // with inheritance
        final BBean src1 = DataFactory.createExtended();
        final BBean dst1 = new BBean();
        MiscUtils.copyValues(src1, dst1);
        checkBeans("Flat copy was not successfull", src1, dst1);
    }

    /**
     * Test for {@link MiscUtils#copyValuesTo(Object, Object, String...)}.
     * 
     * @throws Exception If something went wrong
     */
    @Test
    public void testFlatCopyOnDifferentTypes() throws Exception {
        final ABean src = DataFactory.createSimple();
        final ABeanTO dst = MiscUtils.copyValuesTo(src, new ABeanTO());
        checkDifferentProperties("Flat copy was not successful", src, dst, ABeanTO.ATTR_BIG, ABeanTO.ATTR_AGE, ABeanTO.ATTR_ARRAY, ABeanTO.ATTR_CHECK_SUM,
                ABeanTO.ATTR_DEFINED, ABeanTO.ATTR_FLAGS, ABeanTO.ATTR_LETTER, ABeanTO.ATTR_NAME, ABeanTO.ATTR_SALDO, ABeanTO.ATTR_VALUE);
        assertSame("Nested bean must be the same instance", src.getNested(), dst.getNested());
        assertNull("Ignored property was copied", MiscUtils.copyValuesTo(src, new ABeanTO(), ABean.ATTR_NAME).getName());
    }

    /**
     * Test for {@link MiscUtils#copy(Object)}.
     * 
     * @throws Exception
     */
    @Test
    public void testCopy() throws Exception {
        // simple
        final ABean src = DataFactory.createSimple();
        final ABean dst = MiscUtils.copy(src);
        assertNotSame(src, dst);
        checkBeans("Flat copy was not successfull", src, dst);
        // with inheritance
        final BBean src1 = DataFactory.createExtended();
        final BBean dst1 = MiscUtils.copy(src1);
        assertNotSame(src1, dst1);
        checkBeans("Flat copy was not successfull", src1, dst1);
        final Integer number = new Integer(12);
        assertSame(number, MiscUtils.copy(number));
        assertNull(MiscUtils.copy(null));
    }

    /**
     * Test for {@link MiscUtils#arrayAppend(Object[], Object)}, {@link MiscUtils#arrayAppend(Object[], Object...)}.
     * 
     * @throws Exception
     */
    @Test
    public void testArrayExpand() throws Exception {
        final String[] src = { "foo", "bar" };
        final String[] exp1 = { "foo", "bar", "baz" };
        final String[] exp2 = { "foo", "bar", "baz", "smp", "ftp" };
        assertTrue(Arrays.equals(exp1, MiscUtils.arrayAppend(src, "baz")));
        assertTrue(Arrays.equals(exp2, MiscUtils.arrayAppend(src, "baz", "smp", "ftp")));
    }

    /**
     * Test for {@link ElementValueComparator}.
     * 
     * @throws Exception
     */
    @Test
    public void testComparator() throws Exception {
        final List<ShortBean> src = new ArrayList<ShortBean>();
        src.add(new ShortBean("a", 32, 3.14));
        src.add(new ShortBean("a", 64, 3.14));
        src.add(new ShortBean("b", 8, 3.14));
        src.add(new ShortBean("b", 16, 3.14));
        src.add(new ShortBean("c", 2, 3.14));
        src.add(new ShortBean("c", 4, 3.14));
        final List<ShortBean> dst = new ArrayList<ShortBean>(src);
        final ElementValueComparator<ShortBean> cmp = new ElementValueComparator<ShortBean>(ShortBean.class, ShortBean.ATTR_FOO, ShortBean.ATTR_BAR);
        Collections.shuffle(dst);
        differentOrder("Shuffling failed - rerun the test", src, dst);
        Collections.sort(dst, cmp);
        equalOrder(src, dst);
        Collections.reverse(src);
        Collections.shuffle(dst);
        differentOrder("Shuffling failed - rerun the test", src, dst);
        cmp.setOrder(false);
        Collections.sort(dst, cmp);
        equalOrder(src, dst);
    }

    /**
     * Ensures that the given lists have the same instances at the same place.
     * 
     * @param <T> The type
     * @param src The source list
     * @param dst The destination list
     */
    private <T> void equalOrder(List<T> src, List<T> dst) {
        assertTrue(src.size() == dst.size());
        for (int i = 0, cnt = src.size(); i < cnt; i++) {
            assertSame(src.get(i), dst.get(i));
        }
    }

    /**
     * Ensures that the given lists have not all instances at the same places.
     * 
     * @param <T> The type
     * @param msg The message in case of an error
     * @param src The source list
     * @param dst The destination list
     */
    private <T> void differentOrder(String msg, List<T> src, List<T> dst) {
        assertTrue(src.size() == dst.size());
        boolean same = true;
        for (int i = 0, cnt = src.size(); i < cnt; i++) {
            same &= src.get(i) == dst.get(i);
        }
        assertFalse(msg, same);
    }
}
